local nl = require'luaNumeric'
require 'luaFDTD3D'
local plot = require "Q2DViewerEx"

--=====================================================================--
--初始化参数
local NFBoxView={
	freq_index = 0;
	type_index = 0;
	plot_mode = 0;
	rho_mode = 1;
	scale_type = 1;
	show_mesh = false;
	units_type = 0;
	view_scale = 1;
	show_contours = false;
	auto_contours = true;
	str_contours = '0';
	contours = {};
	colormap = 0;
	range = {0,3};
	auto_range = true;
};
--=====================================================================--

--=====================================================================--
--创建表和创建元表
function NFBoxView:new (o)
	o = o or {};
	self.__index = self;
	setmetatable(o,self)
	o:init();
	return o;
end
--=====================================================================--

--=====================================================================--
--创建表和创建元表
function NFBoxView:init ()

end
--=====================================================================--

--=====================================================================--
--更新数据
function NFBoxView:update_data ()
	local data = self.probe:results_tensor3()
	assert( #data.theta>0, '近远场盒子数据为空' ) 
	self.bbox = self.probe:bbox();
	--error('a')
	--print( data.freq )
	self.freq = data.freq;
	self.theta = data.theta *pi/180;
	self.phi = data.phi*pi/180;
		
	local fields = self:create_fields();
	fields:set_dimention(#self.freq*2)
	--print( 'dimention:',#freq*2 )
	for ii=1,#self.theta do 
		local v = nl.new_cvector(#self.freq*2);
		for jj=1,#self.freq do 
			v[ (jj-1)*2 + 1 ] = data.data[ {ii,jj,1} ];
			v[ (jj-1)*2 + 2 ] = data.data[ {ii,jj,2} ];
		end
		fields:insert( self.theta[ii],self.phi[ii],v );
	end
	self.fields = fields;
	self:update_fields_to_view()
	self:update_scale_to_view();
	self:update_range();
	self:update_selection();
	self:update_contours()
	self:update_colormap_str_to_view();
	self:update_info_str_to_view();
	self:update_scale_to_view();
	self:update_range();
	--self:update_view();
	--print( 'update_fields_to_view')
end

function NFBoxView:refresh_figs ()
	self:update_data();
	self:update_scale_to_view();
	self:update_range();
	self:update_selection();
	self:update_colormap_str_to_view();
	self:update_info_str_to_view();
	self:update_scale_to_view();
	--self:update_view();
	--self:update_view();
end
--=====================================================================--

--=====================================================================--
--获得空气盒子中心位置
function NFBoxView:get_center ()
	if self.bbox then 
		return self.bbox:xcenter(),self.bbox:ycenter(),self.bbox:zcenter();
	end
	return 0,0,0;
end
--=====================================================================--

--=====================================================================--
--获得对应频率的源功率
function NFBoxView:get_source_power (p1,p2)
	p1:clear();p2:clear();
	local freq = self.probe:freq();
	for k,v in pairs(freq) do 
		--d1,d2 = Gallop.FDTDSolver:get_port_power(v);
		d1,d2 = Gallop.FDTDSolver:get_all_lumpedsrc_ports_power(v);		
		p1:add(d1);
		p2:add(d2);
	end
end

function NFBoxView:get_pout (pout)
	pout:clear()
	local pout1 = self.probe:pout();
	for k,v in pairs(pout1) do 
		pout:add(v);
	end
end

function NFBoxView:get_colormap_str ()
	local str = '';
	if self.plot_mode == 0 then
		if self.scale_type == 0 then
			str = 'E (dBV/m)';
		elseif self.scale_type == 1 then
			str = 'E (V/m)';
		elseif self.scale_type == 2 then
			str = 'Arg (E) (arc.)';
		elseif self.scale_type == 3 then
			str = 'Real(E) (V/m)';
		elseif self.scale_type == 4 then
			str = 'Imag(E) (V/m)';
		end
	end
	if self.plot_mode == 1 then
		if self.scale_type == 0 then
			str = 'RCS (dBsm)';
		elseif self.scale_type == 1 then
			str = 'RCS (sm)';
		elseif self.scale_type == 2 then
			str = 'Arg (RCS) (arc.)';
		elseif self.scale_type == 3 then
			str = 'Real(RCS) (V/m)';
		elseif self.scale_type == 4 then
			str = 'Imag(RCS) (V/m)';
		end
	end
	if self.plot_mode == 2 then
		if self.scale_type == 0 then
			str = 'Directivity (dB)';
		elseif self.scale_type == 1 then
			str = 'Directivity';
		end
	end
	if self.plot_mode == 3 then
		if self.scale_type == 0 then
			str = 'Gain (dB)';
		elseif self.scale_type == 1 then
			str = 'Gain';
		end
	end
	if self.plot_mode == 4 then
		if self.scale_type == 0 then
			str = 'Realized Gain (dB)';
		elseif self.scale_type == 1 then
			str = 'Realized Gain';
		end
	end
	return str;
end

function NFBoxView:get_info_str ()
	local str = '';
	if self.plot_mode == 0 then
		str = str .. 'E';
	elseif self.plot_mode == 1 then
		str = str .. 'RCS';
	elseif self.plot_mode == 2 then
		str = str .. 'Directivity';
	elseif self.plot_mode == 3 then
		str = str .. 'Gain';
	elseif self.plot_mode == 4 then
		str = str .. 'Realized Gain';
	end
	
	if self.type_index == 0 then
		str = str .. '(Total)';
	elseif self.type_index == 1 then
		str = str .. '(Theta)';
	elseif self.type_index == 2 then
		str = str .. '(Phi)';
	elseif self.type_index == 3 then
		str = str .. '(Left-handed)';
	elseif self.type_index == 4 then
		str = str .. '(Right-handed)';
	end
	if self.units_type==0 then
		str = str .. ' @ Frequency: ' .. self.freq[ self.freq_index  + 1] .. ' ' .. Geometry.ref_units_freq_str();
	else
		local wavelength = c0 / self.freq[ self.freq_index  + 1] / Geometry.ref_units_dim()  / Geometry.ref_units_freq();
		str = str .. ' @ Wavelength: ' .. wavelength .. ' ' .. Geometry.ref_units_dim_str();
	end
	return str;
end
--=====================================================================--

--=====================================================================--
--导出数据
function NFBoxView:export_data (filename, opt)
	local freq = self.probe:freq();
	local ddd = nl.new_vector(#freq);
	for ii=1,#freq do 
	    ptotal,pout =  Gallop.FDTDSolver:get_port_power (freq[ii])
	    ddd[ii] = ptotal;
	 end
	--if opt == 'E-field(V/m)' then
		self.probe:save( filename,opt, ddd)
	--else
		--self.probe:save( filename,opt)	
	--end
end
--=====================================================================--


--=====================================================================--
--更新画图函数:对应对一个复选框
function NFBoxView:change_selection (fidx,tidx)
	assert( fidx>=0 and fidx < #self.freq, '超出范围，或者参数类型不匹配' )
	assert( tidx>=0 and tidx < 5, '超出范围，或者参数类型不匹配' )
	self.freq_index = fidx;
	self.type_index = tidx;
	self:update_selection();
	self:update_scale_type_to_view();
	self:update_range();
	self:update_colormap_str_to_view();
	self:update_info_str_to_view();
	self:update_contours()
	self:update_view();
	self:update_parameters_to_ui();
end
--=====================================================================--

--=====================================================================--
--更新画图函数:对应对一个复选框
function NFBoxView:change_plot_mode (s)
	assert( s>=0 and s <= 4, '超出范围，或者参数类型不匹配' )
	self.plot_mode = s;
	self:update_scale_type_to_view();
	self:update_range();
	self:update_colormap_str_to_view();
	self:update_info_str_to_view();
	self:update_contours()
	self:update_parameters_to_ui();
	--self:update_range();
	self:update_view();
end
--=====================================================================--

--=====================================================================--
--更新画图函数:对应scale type
function NFBoxView:change_scale_type (s)
	assert( s>=0 and s <= 4, '超出范围，或者参数类型不匹配' )
	self.scale_type = s;
	self:update_scale_type_to_view();
	self:update_range();
	self:update_colormap_str_to_view();
	self:update_info_str_to_view();
	self:update_contours()
	self:update_view();
	self:update_parameters_to_ui();
	self:update_view();
end
--=====================================================================--

--=====================================================================--
--更新网格
function NFBoxView:change_show_mesh(s)
	assert( s==true or s == false, '参数类型不匹配' )
	if s ~= self.show_mesh then 
		self.show_mesh = s;
		self.fields:is_show_meshline(s);
		self:update_view();
		self:update_parameters_to_ui();
		self:update_contours()
	end
end
--=====================================================================--

--=====================================================================--
--更新画图比例
function NFBoxView:change_view_scale (s)
	assert( s>=0 and s <= 100, '超出范围，或者参数类型不匹配' )
	if s~= self.view_scale then 
		self.view_scale = s;
		self:update_scale_to_view();
		self:update_scale_to_ui();
		self:update_view();
		self:update_view();
		self:update_contours()
	end
end
--=====================================================================--

--=====================================================================--
--更新网格
function NFBoxView:change_show_contours(s)
	assert( s==true or s == false, '参数类型不匹配' )
	if s ~= self.show_contours then 
		self.show_contours = s;
		self.fields:show_contours(s);
		self:update_view();
		self:update_view();
		self:update_parameters_to_ui();
		self:update_view();
		self:update_contours()
		self:update_view();
	end
end
--=====================================================================--

--=====================================================================--
--修改自动更新等高线
function NFBoxView:change_auto_contours (set)
	assert( set==true or set == false, '参数类型不匹配,期望bool, 实际:' .. type(set))
	if s~= self.auto_contours then 
		self.auto_contours = set;
		self:update_contours()
		self:update_view();
	end
end
--=====================================================================--

--=====================================================================--
--自动更新颜色条取值范围
function NFBoxView:update_contours ()
	if self.fields then		
		--print('str',self.auto_contours);
		if self.auto_contours==true then 
			local str = self:get_auto_contours_str()
			self.contours = nl.new_vector(str);
		else
			self.contours = nl.new_vector(self.str_contours);
		end
		self.fields:clear_contours();
		for k,v in pairs(self.contours) do 
			self.fields:cut_segment_plane(v);
		end
	end
end
--=====================================================================--

--=====================================================================--
--自动更新等高线数值范围
function NFBoxView:get_auto_contours_str ()
	if self.fields then		
		local range = {self.fields:value_range()};
		local str = '';
		if self.scale_type == 0 then 
			str = (range[2]-3) ..';'..(range[2]-10);
		elseif self.scale_type == 1 then 
			str = (range[2]/2) ..';'..(range[2]/10);
		end
		return str;
	end
	return '';
end
--=====================================================================--

--=====================================================================--
--自动更新颜色条取值范围
function NFBoxView:refresh_contours ()
	if self.fields then		
		self.str_contours = self:get_auto_contours_str()
		self:update_contours_str_to_ui(self.str_contours);
	end
end
--=====================================================================--


--=====================================================================--
--更新画图颜色条
function NFBoxView:change_colormap (s)
	--assert( s>=0 and s <= 5, '超出范围，或者参数类型不匹配' )
	self.colormap = s;
	self:update_colormap_to_view();
	self:update_view();
end
--=====================================================================--

--=====================================================================--
--更新画图函数
function NFBoxView:update_range()
	self:update_auto_range_to_ui(self.auto_range);
	if self.fields and self.auto_range then
		self.range = { self.fields:value_range() };
	end
	self:update_range_to_ui(self.range[1],self.range[2]);
	self:update_range_to_view(self.range[1],self.range[2]);
	--self:update_view()
end
--=====================================================================--

--=====================================================================--
--修改自动更新
function NFBoxView:change_auto_range (set)
	self.auto_range = set;
	self:update_range();
	self:update_view();
end
--=====================================================================--

--=====================================================================--
--自动更新颜色条取值范围
function NFBoxView:refresh_range ()
	if self.fields then		
		self.range = { self.fields:value_range() };
	end
	self:update_range();
	self:update_view();
end
--=====================================================================--

--=====================================================================--
--自动更新等高线
function NFBoxView:refresh_contours ()
	self.str_contours = self:get_auto_contours_str();
	self:update_contours_str_to_ui( self.str_contours );
end
--=====================================================================--



--=====================================================================--
--更新颜色条取值范围
function NFBoxView:change_range_min ( v )
	self.range[1] = v
	self:update_range();
	self:update_view();
end
function NFBoxView:change_range_max ( v )
	self.range[2] = v
	self:update_range();
	self:update_view();
end
function NFBoxView:change_range ( v1,v2 )
	self.range = {v1,v2}
	self:update_range();
	self:update_view();
end
--=====================================================================--

--=====================================================================--
--更新画图单位
function NFBoxView:change_units_type (s)
	assert( s>=0 and s <= 1, '超出范围，或者参数类型不匹配' )
	if s~= self.units_type then 
		self.units_type = s;
		self:update_info_str_to_view();
		self:update_view();
		--self:update_view();
		self:update_parameters_to_ui();
	end
end
--=====================================================================--

--=====================================================================--
--更新画图单位
function NFBoxView:change_contours (s)
	if s~= self.str_contours then 
		self.str_contours = s;
		self:update_contours();
	end
end
--=====================================================================--

--=====================================================================--
--更新rho画图形式
function NFBoxView:change_rho_mode (s)
	assert( s>=1 and s <= 2, '超出范围，或者参数类型不匹配' )
	if s~= self.rho_mode then 
		self.rho_mode = s;
		self:update_rho_mode_to_view();
		self:update_parameters_to_ui();
		self:update_view();
	end
end
--=====================================================================--

--=====================================================================--
--查看数据
function NFBoxView:view_data ()
	if self.fields then	
		local data = nl.new_eigen_smatrix(#self.theta,3)
		for kk=1,#self.theta do 
			data[{kk,1}] = tostring(self.theta[kk]*180/pi);
			data[{kk,2}] =  tostring(self.phi[kk]*180/pi);
			data[{kk,3}] = tostring(self.fields:value(kk-1));
		end
		self.dataView  = Gallop.DataPost:create_data_table_to_ui();
		self.dataView:set_data(data);
		
		local header = nl.new_svector();
		header:add('方位角 [deg.]')
		header:add('极化角 [deg.]')
		header:add(self:get_info_str())	
		self.dataView:set_header(header);
	end
end
--=====================================================================--

--=====================================================================--
--查看数据
function NFBoxView:export_all_figs (path)
	for ii=1,#self.freq do
		self.freq_index = ii-1;
		self:update_selection();
		self:update_scale_to_view();
		self:update_range();
		self:update_colormap_str_to_view();
		self:update_info_str_to_view();
		self:update_view();
		self:update_view();
		self.view:saveSnapShot( path .. '/' .. 'f-' ..  self.freq[ ii ] .. '.jpg' )
	end
end
--=====================================================================--
return NFBoxView;
